package net.crozz.openapi.weibo;

import net.crozz.openapi.ApiException;
import net.crozz.openapi.http.Param;
import net.crozz.openapi.http.Requester;
import net.crozz.openapi.weibo.model.Display;
import net.crozz.openapi.weibo.model.Resp_access_token;
import net.crozz.openapi.weibo.model.Resp_get_token_info;
import net.crozz.openapi.weibo.model.Scope;
import org.apache.commons.lang.StringUtils;

public class Weibo {
    private static final String BASE_URL        = "https://api.weibo.com/2/";
    private static final String AUTHORIZE_URL   = "https://api.weibo.com/oauth2/authorize";
    private static final String ACCESSTOKEN_URL = "https://api.weibo.com/oauth2/access_token";
    public final Account   account;
    public final Common    common;
    public final Short_url short_url;
    public final Users     users;
    public final Statuses  statuses;
    private final Requester client;
    private final String    client_id;
    private final String    client_secret;
    private final String    redirect_uri;

    public Weibo(Requester client, String client_id, String client_secret, String redirect_uri) {
        this.client = client;
        this.client_id = client_id;
        this.client_secret = client_secret;
        this.redirect_uri = redirect_uri;

        this.account = new Account(client, BASE_URL);
        this.common = new Common(client, BASE_URL);
        this.short_url = new Short_url(client, BASE_URL);
        this.users = new Users(client, BASE_URL);
        this.statuses = new Statuses(client, BASE_URL);
    }

    /**
     * OAuth2的authorize接口<br/>
     * 从 {@link Weibo} 从获取clientId，scope 使用 {@link Scope#ALL}，其余参数默认
     *
     * @see Weibo#authorize(String, String, Scope[], String, Display, Boolean, String)
     */
    public String authorize() {
        return authorize(client_id, redirect_uri, new Scope[]{Scope.ALL}, null, null, null, null);
    }

    /**
     * OAuth2的authorize接口<br/>
     * 文档地址：http://open.weibo.com/wiki/Oauth2/authorize
     *
     * @param client_id    申请应用时分配的AppKey。
     * @param redirect_uri 授权回调地址，站外应用需与设置的回调地址一致，站内应用需填写canvas page的地址。
     * @param scope        申请scope权限所需参数，可一次申请多个scope权限，用逗号分隔。<a
     *                     href="http://open.weibo.com/wiki/Scope">使用文档</a>
     * @param state        用于保持请求和回调的状态，在回调时，会在Query
     *                     Parameter中回传该参数。开发者可以用这个参数验证请求有效性，
     *                     也可以记录用户请求授权页前的位置。这个参数可用于防止跨站请求伪造（CSRF）攻击
     * @param display      授权页面的终端类型，取值见下面的说明。
     * @param forcelogin   是否强制用户重新登录，true：是，false：否。默认false。
     * @param language     授权页语言，缺省为中文简体版，en为英文版。
     */
    public String authorize(
            String client_id, String redirect_uri, Scope[] scope, String state,
            Display display, Boolean forcelogin, String language
    ) {
        String scopeStr = null;
        if (scope != null) {
            scopeStr = StringUtils.join(scope, ",");
        }

        return Requester.makeUrl(
                AUTHORIZE_URL,
                Param.newParam("client_id", client_id),
                Param.newParam("redirect_uri", redirect_uri),
                Param.newParam("scope", scopeStr),
                Param.newParam("state", state),
                Param.newParam("display", display),
                Param.newParam("forcelogin", forcelogin),
                Param.newParam("language", language)
        );
    }

    /**
     * OAuth2的access_token接口<br/>
     * http://open.weibo.com/wiki/OAuth2/access_token
     * client_id 使用 Weibo.client_id<br/>
     * client_secret 使用 Weibo.client_secret<br/>
     * grant_type 使用 "authorization_code"<br/>
     * redirect_uri 使用 Weibo.redirect_uri<br/>
     *
     * @param code <b color='red'>grant_type为authorization_code时</b>，调用authorize获得的code值。
     *
     * @see Weibo#access_token(String, String, String, String, String)
     */
    public Resp_access_token access_token(String code) throws ApiException {
        return access_token(client_id, client_secret, code, redirect_uri);
    }

    /**
     * OAuth2的access_token接口<br/>
     * http://open.weibo.com/wiki/OAuth2/access_token
     * grant_type 使用 "authorization_code"，其余参数默认
     *
     * @param client_id     申请应用时分配的AppKey。
     * @param client_secret 申请应用时分配的AppSecret。
     * @param code          <b color='red'>grant_type为authorization_code时</b>，调用authorize获得的code值。
     * @param redirect_uri  <b color='red'>grant_type为authorization_code时</b>，回调地址，需需与注册应用里的回调地址一致。
     *
     * @see Weibo#access_token(String, String, String, String, String)
     */
    public Resp_access_token access_token(
            String client_id, String client_secret,
            String code, String redirect_uri
    ) throws ApiException {
        return access_token(client_id, client_secret, "authorization_code", code, redirect_uri);
    }

    /**
     * OAuth2的access_token接口<br/>
     * http://open.weibo.com/wiki/OAuth2/access_token
     *
     * @param client_id     申请应用时分配的AppKey。
     * @param client_secret 申请应用时分配的AppSecret。
     * @param grant_type    请求的类型，填写"authorization_code"
     * @param code          <b color='red'>grant_type为authorization_code时</b>，调用authorize获得的code值。
     * @param redirect_uri  <b color='red'>grant_type为authorization_code时</b>，回调地址，需需与注册应用里的回调地址一致。
     */
    public Resp_access_token access_token(
            String client_id, String client_secret, String grant_type,
            String code, String redirect_uri
    ) throws ApiException {
        return client.postObj(
                Resp_access_token.class,
                ACCESSTOKEN_URL,
                Param.newParam("client_id", client_id),
                Param.newParam("client_secret", client_secret),
                Param.newParam("grant_type", grant_type),
                Param.newParam("code", code),
                Param.newParam("redirect_uri", redirect_uri)
        );
    }

    /**
     * 查询用户access_token的授权相关信息，包括授权时间，过期时间和scope权限。<br/>
     * http://open.weibo.com/wiki/Oauth2/get_token_info
     *
     * @param access_token 用户授权时生成的access_token。
     */
    public Resp_get_token_info get_token_info(String access_token) throws ApiException {
        return client.postObj(
                Resp_get_token_info.class,
                "https://api.weibo.com/oauth2/get_token_info",
                Param.newParam("access_token", access_token)
        );
    }

}
